<!doctype html>
<html lang="zh">
<head>
  <meta charset="utf-8" />
  <title>WebSocket 达人匹配测试</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      max-width: 800px;
      margin: 0 auto;
      padding: 20px;
    }
    .container {
      display: flex;
      flex-direction: column;
      gap: 20px;
    }
    .controls {
      display: flex;
      gap: 10px;
      margin-bottom: 20px;
      flex-wrap: wrap;
    }
    button {
      padding: 10px 20px;
      background-color: #4CAF50;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
    button:hover {
      background-color: #45a049;
    }
    #log {
      border: 1px solid #ddd;
      padding: 15px;
      height: 400px;
      overflow-y: auto;
      background-color: #f9f9f9;
    }
    .user-message {
      color: blue;
    }
    .bot-message {
      color: green;
    }
    .error-message {
      color: red;
    }
    textarea {
      width: 100%;
      padding: 10px;
      box-sizing: border-box;
      margin-bottom: 10px;
    }
    .audit-modal {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      z-index: 1000;
      justify-content: center;
      align-items: center;
    }
    .audit-content {
      background-color: white;
      padding: 20px;
      border-radius: 5px;
      width: 90%;
      max-width: 600px;
      max-height: 80vh;
      overflow-y: auto;
    }
    .audit-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;
    }
    .audit-buttons {
      display: flex;
      gap: 10px;
      justify-content: flex-end;
      margin-top: 20px;
    }
    .audit-field {
      margin-bottom: 15px;
    }
    .audit-field label {
      display: block;
      margin-bottom: 5px;
      font-weight: bold;
    }
    .audit-field input[type="text"],
    .audit-field input[type="number"] {
      width: 100%;
      padding: 8px;
      box-sizing: border-box;
    }
    .audit-field textarea {
      height: 150px;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>WebSocket 达人匹配测试</h1>
    
    <div>
      <h3>请求数据</h3>
      <textarea id="requestData">{  
  "main_req": "寻找美妆领域的达人",
  "budget": 5000,
  "fans_req": "18-35岁女性",
  "output_req": "短视频内容",
  "other_req": "有护肤产品推广经验"
}</textarea>
    </div>
    
    <div class="controls">
      <button id="connectBtn">连接WebSocket</button>
      <button id="startMatchBtn">开始同步匹配</button>
      <button id="startAsyncMatchBtn">开始异步匹配</button>
      <button id="disconnectBtn">断开连接</button>
    </div>
    
    <div>
      <h3>日志输出</h3>
      <div id="log"></div>
    </div>
  </div>
  
  <!-- 审核对话框 -->
  <div id="auditModal" class="audit-modal">
    <div class="audit-content">
      <div class="audit-header">
        <h2>关键词人工审核</h2>
        <span id="closeModal" style="cursor: pointer; font-size: 24px;">&times;</span>
      </div>
      
      <div class="audit-field">
        <label for="originalKeywords">原始关键词:</label>
        <textarea id="originalKeywords" readonly></textarea>
      </div>
      
      <div class="audit-field">
        <label for="mappedKeywords">映射关键词:</label>
        <textarea id="mappedKeywords" readonly></textarea>
      </div>
      
      <div class="audit-field">
        <label for="isApproved">是否通过审核:</label>
        <input type="radio" id="approveYes" name="isApproved" value="true" checked> 是
        <input type="radio" id="approveNo" name="isApproved" value="false"> 否
      </div>
      
      <div class="audit-field">
        <label for="auditScore">审核分数 (0-100):</label>
        <input type="number" id="auditScore" min="0" max="100" value="80">
      </div>
      
      <div class="audit-field">
        <label for="comments">审核意见:</label>
        <textarea id="comments"></textarea>
      </div>
      
      <div class="audit-field" id="correctedKeywordsField">
        <label for="correctedKeywords">修正后的关键词:</label>
        <textarea id="correctedKeywords"></textarea>
      </div>
      
      <div class="audit-field">
        <label for="auditorId">审核员ID:</label>
        <input type="text" id="auditorId" value="test_auditor">
      </div>
      
      <div class="audit-buttons">
        <button id="cancelAudit">取消</button>
        <button id="submitAudit">提交审核</button>
      </div>
    </div>
  </div>

  <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
  <script>
    const log = document.getElementById('log');
    const requestData = document.getElementById('requestData');
    const connectBtn = document.getElementById('connectBtn');
    const startMatchBtn = document.getElementById('startMatchBtn');
    const startAsyncMatchBtn = document.getElementById('startAsyncMatchBtn');
    const disconnectBtn = document.getElementById('disconnectBtn');
    
    let socket = null;
    let clientId = null;
    
    // 记录日志
    function appendLog(message, type = 'info') {
      const logEntry = document.createElement('div');
      logEntry.className = type === 'user' ? 'user-message' : 
                          type === 'bot' ? 'bot-message' : 
                          type === 'error' ? 'error-message' : 'info-message';
      logEntry.innerText = `[${new Date().toLocaleTimeString()}] ${message}`;
      log.appendChild(logEntry);
      log.scrollTop = log.scrollHeight;
    }
    
    // 连接WebSocket
    connectBtn.addEventListener('click', () => {
      if (socket && socket.connected) {
        appendLog('已经连接到服务器', 'info');
        return;
      }
      
      // 连接到WebSocket服务器
      socket = io('http://localhost:5000', {
        path: '/socket.io',  // 使用SocketIO默认路径
        transports: ['websocket']
      });
      
      // 连接成功
      socket.on('connect', () => {
        appendLog('WebSocket连接成功', 'info');
        startMatchBtn.disabled = false;
        startAsyncMatchBtn.disabled = false;
        disconnectBtn.disabled = false;
        connectBtn.disabled = true;
      });
      
      // 连接响应
      socket.on('connect_response', (data) => {
        clientId = data.client_id;
        appendLog(`接收到客户端ID: ${clientId}`, 'bot');
      });
      
      // 匹配更新
      socket.on('match_update', (data) => {
        appendLog(`匹配更新: ${JSON.stringify(data)}`, 'bot');
      });
      
      // 匹配完成
      socket.on('match_complete', (data) => {
        appendLog(`匹配完成: ${JSON.stringify(data)}`, 'bot');
      });
      
      // 连接断开
      socket.on('disconnect', () => {
        appendLog('WebSocket连接断开', 'info');
        startMatchBtn.disabled = true;
        startAsyncMatchBtn.disabled = true;
        disconnectBtn.disabled = true;
        connectBtn.disabled = false;
      });
      
      // 错误处理
      socket.on('error', (error) => {
        appendLog(`错误: ${error}`, 'error');
      });
      
      // 审核请求
      socket.on('audit_request', (data) => {
        appendLog(`接收到审核请求: ${JSON.stringify(data)}`, 'bot');
        
        // 保存请求ID
        currentAuditRequestId = data.request_id;
        
        // 填充审核对话框
        const auditData = data.audit_data;
        document.getElementById('originalKeywords').value = auditData.original_keywords || '';
        document.getElementById('mappedKeywords').value = auditData.mapped_keywords || '';
        document.getElementById('comments').value = '';
        document.getElementById('correctedKeywords').value = auditData.mapped_keywords || '';
        
        // 显示审核对话框
        document.getElementById('auditModal').style.display = 'flex';
      });
      
      // 审核更新
      socket.on('audit_update', (data) => {
        appendLog(`审核更新: ${JSON.stringify(data)}`, 'bot');
      });
    });
    
    // 开始同步匹配
    startMatchBtn.addEventListener('click', () => {
      if (!socket || !socket.connected) {
        appendLog('请先连接WebSocket', 'error');
        return;
      }
      
      try {
        const data = JSON.parse(requestData.value);
        socket.emit('start_match', data);
        appendLog(`发送同步匹配请求: ${JSON.stringify(data)}`, 'user');
      } catch (e) {
        appendLog(`请求数据格式错误: ${e.message}`, 'error');
      }
    });
    
    // 开始异步匹配
    startAsyncMatchBtn.addEventListener('click', () => {
      if (!socket || !socket.connected) {
        appendLog('请先连接WebSocket', 'error');
        return;
      }
      
      try {
        const data = JSON.parse(requestData.value);
        socket.emit('start_async_match', data);
        appendLog(`发送异步匹配请求: ${JSON.stringify(data)}`, 'user');
      } catch (e) {
        appendLog(`请求数据格式错误: ${e.message}`, 'error');
      }
    });
    
    // 断开连接
    disconnectBtn.addEventListener('click', () => {
      if (socket) {
        socket.disconnect();
        socket = null;
        clientId = null;
        appendLog('已主动断开WebSocket连接', 'info');
      }
    });
    
    // 关闭审核对话框
    document.getElementById('closeModal').addEventListener('click', () => {
      document.getElementById('auditModal').style.display = 'none';
    });
    
    // 取消审核
    document.getElementById('cancelAudit').addEventListener('click', () => {
      document.getElementById('auditModal').style.display = 'none';
    });
    
    // 审核选择事件
    document.getElementById('approveYes').addEventListener('change', () => {
      document.getElementById('correctedKeywordsField').style.display = 'none';
    });
    
    document.getElementById('approveNo').addEventListener('change', () => {
      document.getElementById('correctedKeywordsField').style.display = 'block';
    });
    
    // 提交审核结果
    document.getElementById('submitAudit').addEventListener('click', () => {
      if (!socket || !socket.connected || !currentAuditRequestId) {
        appendLog('无法提交审核结果，请检查连接', 'error');
        return;
      }
      
      // 构建审核结果
      const auditResult = {
        is_approved: document.getElementById('approveYes').checked,
        audit_score: parseInt(document.getElementById('auditScore').value) || 0,
        comments: document.getElementById('comments').value,
        corrected_keywords: document.getElementById('correctedKeywords').value,
        auditor_id: document.getElementById('auditorId').value,
        audit_time: new Date().toISOString()
      };
      
      // 发送审核结果
      socket.emit('audit_response', {
        request_id: currentAuditRequestId,
        audit_result: auditResult
      });
      
      appendLog(`提交审核结果: ${JSON.stringify(auditResult)}`, 'user');
      
      // 关闭对话框
      document.getElementById('auditModal').style.display = 'none';
      currentAuditRequestId = null;
    });
    
    // 点击模态框外部关闭
    window.addEventListener('click', (event) => {
      if (event.target === document.getElementById('auditModal')) {
        document.getElementById('auditModal').style.display = 'none';
      }
    });
    
    // 初始化按钮状态
    startMatchBtn.disabled = true;
    startAsyncMatchBtn.disabled = true;
    disconnectBtn.disabled = true;
    document.getElementById('correctedKeywordsField').style.display = 'none';
    
    // 当前审核请求ID
    let currentAuditRequestId = null;
  </script>
</body>
</html>